<?php
namespace app\api\controller;
use app\common\model\Channel;
use think\Controller;
use think\facade\Log;
use app\common\model\Order;
use app\common\model\Gameplog;
use app\common\model\Gamelist;
use app\common\model\GameOrderNotify;
use app\common\model\OrderLog;
use think\Db;

class GameNotify extends Controller
{
    /**
     * 通知到游戏发货
     * @param string $orderNum 订单号
     * @return array 返回通知结果
     */
    public function game_notify($orderNum)
    {
        try {
            $order = Order::where('order_no', $orderNum)->find();
            if (!$order) {
                Log::error('游戏发货通知订单不存在：' . $orderNum);
                return ['status' => false, 'message' => '游戏发货通知订单不存在'];
            }

            if (!in_array($order['order_status'],[1,2,4])){
                Log::error('游戏发货通知订单状态异常：' . $orderNum);
                return ['status' => false, 'message' => '游戏发货通知订单状态异常'];
            }

            $game = GameList::where('id', $order->gid)->find();

            if (!$game || empty($game->api_pay_url)) {
                Log::error('游戏发货通知缺少发货地址，游戏ID：' . $order->gid);
                return ['status' => false, 'message' => '游戏发货通知缺少发货地址，游戏ID：' . $order->gid];
            }

            // 准备通知数据
            $notifyData = $this->prepareNotifyData($order,$game);
            log::info('游戏发货请求数据：' . json_encode($notifyData));
            // 执行通知
            $result = $this->doNotify($game->api_pay_url, $notifyData, 3);

            log::info('游戏发货通知结果：' . json_encode($result));
            // 记录通知结果
            $this->saveNotifyResult($order, $game->api_pay_url, $notifyData, $result);

            if($result['status']) {
                try {
                    DB::startTrans();
                    // 发货成功
                    $order->order_status = 3;
                    $order->save();
                    //渠道上报
                    $cid_arr = [5];
                    if(in_array($order->cid, $cid_arr)){
                        $channel = Channel::where('id', $order->cid)->find();
                        // 动态加载自定义类（例如：app\common\CustomClass
                        $className ="app\index\channel\\". ucfirst($channel['username']);; // 替换为你的类名
                        if (!class_exists($className)) {
                            Log::info("渠道类初始化失败");
                        }
                        //自动注册
                        $gameapi = new $className();
                        $res = $gameapi->order_report($order);
                    }
                    Db::commit();
                    OrderLog::addLog($order->order_no, $order->order_status, $order->type, $order->trade_no, '发货成功');
                }catch (Exception $e) {
                    Db::rollback();
                    Log::error('游戏发货通知订单状态更新失败：' . $e->getMessage());
                }

            }
            //更新订单状态0=已下单 1=已支付 2=已通知 3=已发货 -1=已取消 4 通知失败

            return $result;

        } catch (\Exception $e) {
            Log::error('游戏发货通知系统异常：' . $e->getMessage());
            return [
                'status' => false,
                'message' => $e->getMessage()
            ];
        }
    }

    /**
     * 游戏通知测试
     * @return void
     */
    public function game_notift_test()
    {
        $data = $this->request->post();
        Log::error('接收渠道订单通知：' . json_encode($data));
        echo 'SUCCESS'; // 测试 游戏通知响应示例 一般都是返回SUCCESS OK 等
    }

    /**
     * 执行通知操作
     * @param string $url 通知地址
     * @param array $data 通知数据
     * @param int $retry 剩余重试次数
     * @return array 通知结果
     */
    private function doNotify($url, $data)
    {
        try {
            $response = $this->curlPostJson($url, $data);

            log::info('游戏发货请求通知结果：' . json_encode($response));
            if ($response['http_code'] == 200) {
                if ($response['body'] === "SUCCESS") {
                    return [
                        'status' => true,
                        'message' => '通知成功',
                        'http_code' => $response['http_code'],
                        'response' => $response['body']
                    ];
                }
            }
        } catch (\Exception $e) {
            $errorMsg = '游戏发货通知失败，HTTP状态码：' . $response['http_code'] . '，响应：' . $response['body'];
            Log::error($errorMsg);
            return [
                'status' => false,
                'message' => $e->getMessage(),
                'http_code' => $response['http_code'] ?? 0,
                'response' => $response['body'] ?? ''
            ];
        }
    }

    /**
     * CURL POST JSON请求
     * @param string $url 请求地址
     * @param array $data 请求数据
     * @return array 响应结果
     */
    private function curlPostJson($url, $data)
    {

        $jsonData = json_encode($data);
        $ch = curl_init();

        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $jsonData,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Content-Length: ' . strlen($jsonData)
            ],
            CURLOPT_TIMEOUT => 10,
            CURLOPT_CONNECTTIMEOUT => 5
        ]);

        $body = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            Log::error('游戏发货CURL请求错误：' . json_encode($error));
        }
        return [
            'http_code' => $httpCode,
            'body' => $body
        ];
    }

    /**
     * 保存通知结果
     * @param object $order 订单数据
     * @param string $notifyUrl 通知地址
     * @param array $notifyData 通知数据
     * @param array $result 通知结果
     * @return void
     */
    private function saveNotifyResult($order, $notifyUrl, $notifyData, $result)
    {

        try {
            $record = [
                'oid' => $order->id,
                'gid' => $order->gid,
                'order_no' => $order->order_no,
                'notify_url' => $notifyUrl,
                'notify_data' => json_encode($notifyData),
                'return_msg' => is_array($result) ? json_encode($result) : $result,
                'notify_time' => date('Y-m-d H:i:s'),
                'notify_status' => $result['status'] ? 1 : 0
            ];
            GameOrderNotify::create($record);
            if (!$result['status']) {
                Log::error('游戏发货通知失败记录，订单号：' . $order->order_no . '，错误：' . $result['message']);
            } else {
                Log::info('游戏发货通知成功记录，订单号：' . $order->order_no);
            }
        } catch (\Exception $e) {
            Log::error('保存游戏发货通知记录失败：' . $e->getMessage());
        }
    }

    /**
     * 准备通知数据
     * @param object $order 订单数据
     * @return array 通知数据
     */
    private function prepareNotifyData($order,$game)
    {
        $uid = $order->uid;
        // 青云诀订单处理
        $grr = [30];
        if(in_array($order->gid,$grr)){
            $py_info = explode("_",$order->order_no);
            Log::error('青云诀订单处理：' . json_encode($py_info));
            if($py_info[0] != $order->uid){
                $uid = $py_info[0];
            }
        }

        $old_grr = [81,82,83,84,85,86,87,88,86,91,
            92,93,94,95,96,97,98,99,100,101,102];
        if(in_array($order->gid, $old_grr)){
            $py_info = explode("_",$order->order_no);
            Log::error('旧版sdk订单处理：' . json_encode($py_info));
            if($py_info[0] != $order->uid){
                $uid = (int) $py_info[0];
            }
        }

        $return = [
            'order_no' => $order->order_no,
            'gid' => $order->gid,
            'uid' => $uid,
            'amount' => round($order->amount * 100),
            'note' => $order->note,
            'pay_time' =>$order->pay_time,
        ];
        $return['sign'] = get_sign($return,$game->pay_key);
        return $return;
    }
}
